package com.ctshk.rpc.order.tour.service.impl;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.ApprovalStatus;
import com.ctshk.common.enums.SysApprovalType;
import com.ctshk.common.enums.SystemBusinessType;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.rpc.order.tour.code.CheckStatusCode;
import com.ctshk.rpc.order.tour.code.ConstantsCode;
import com.ctshk.rpc.order.tour.code.IsDeletedCode;
import com.ctshk.rpc.order.tour.code.SeriesOrderErrorCode;
import com.ctshk.rpc.order.tour.code.SeriesOrderTouristOtherFeeFeeTypeCode;
import com.ctshk.rpc.order.tour.dto.SeriesOrderDiscountListDTO;
import com.ctshk.rpc.order.tour.entity.SeriesOrderAmountStatistics;
import com.ctshk.rpc.order.tour.entity.SeriesOrderDiscount;
import com.ctshk.rpc.order.tour.entity.SeriesOrderTouristInfo;
import com.ctshk.rpc.order.tour.entity.SeriesOrderTouristOtherFee;
import com.ctshk.rpc.order.tour.mapper.SeriesOrderAmountStatisticsMapper;
import com.ctshk.rpc.order.tour.mapper.SeriesOrderDiscountMapper;
import com.ctshk.rpc.order.tour.mapper.SeriesOrderTouristInfoMapper;
import com.ctshk.rpc.order.tour.mapper.SeriesOrderTouristOtherFeeMapper;
import com.ctshk.rpc.order.tour.req.SeriesOrderDiscountAddReq;
import com.ctshk.rpc.order.tour.req.SeriesOrderDiscountApprovalReq;
import com.ctshk.rpc.order.tour.req.SeriesOrderDiscountDeleteReq;
import com.ctshk.rpc.order.tour.req.SeriesOrderDiscountEditReq;
import com.ctshk.rpc.order.tour.req.SeriesOrderDiscountListReq;
import com.ctshk.rpc.order.tour.service.ISeriesOrderDiscountService;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.service.ISysUserService;
import com.ctshk.rpc.workflow.dto.ApprovalCheckDTO;
import com.ctshk.rpc.workflow.dto.ApprovalStartDTO;
import com.ctshk.rpc.workflow.service.ISysApprovalService;

/**
 * <p>
 * 系列团折扣记录 服务实现类
 * </p>
 *
 * @author 谭响
 * @since 2021-01-22
 */
@DubboService
public class SeriesOrderDiscountServiceImpl extends ServiceImpl<SeriesOrderDiscountMapper, SeriesOrderDiscount> implements ISeriesOrderDiscountService {

    @Autowired
    private SeriesOrderTouristInfoMapper seriesOrderTouristInfoMapper;

    @Autowired
    private SeriesOrderAmountStatisticsMapper seriesOrderAmountStatisticsMapper;

    @Autowired
    private SeriesOrderTouristOtherFeeMapper seriesOrderTouristOtherFeeMapper;

    @Autowired
    private SeriesOrderDiscountMapper seriesOrderDiscountMapper;

    @DubboReference
    private ISysUserService iSysUserService;

    @DubboReference
    private ISysApprovalService iSysApprovalService;

    /**
     * 添加
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result add(SeriesOrderDiscountAddReq req) {
        //该用户是否申请过折扣
        List<SeriesOrderDiscount> seriesOrderDiscounts = seriesOrderDiscountMapper.queryByTourist(req.getOrderId(),req.getTouristId());
        if (CollectionUtils.isNotEmpty(seriesOrderDiscounts)){
            throw new BusinessException(SystemError.CUSTOM_ORDER_4010);
        }
        SeriesOrderDiscount discount = EntityUtil.copy(req, SeriesOrderDiscount.class);
        discount.setId(IdWorker.getId());
        discount.setCheckStatus(CheckStatusCode.APPROVAL.getCode());
        LocalDateTime now = LocalDateTime.now();
        discount.setGmtCreate(now);
        discount.setGmtModified(now);
        discount.setCreateId(req.getUserId());
        discount.setModifiedId(req.getUserId());
        discount.setIsDeleted(IsDeletedCode.NO.getCode());
        QueryWrapper<SeriesOrderTouristInfo> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.lambda().eq(SeriesOrderTouristInfo::getOrderId, req.getOrderId());
        queryWrapper2.lambda().eq(SeriesOrderTouristInfo::getId, req.getTouristId());
        queryWrapper2.lambda().eq(SeriesOrderTouristInfo::getIsDeleted, IsDeletedCode.NO.getCode());
        SeriesOrderTouristInfo touristInfo = seriesOrderTouristInfoMapper.selectOne(queryWrapper2);
        discount.setBeforeAmount(touristInfo.getTotalReceivables());
        boolean save = save(discount);
        if (!save){
            throw new BusinessException(SystemError.SYS_437);
        }
        Map<String, Object> extendParams = new HashMap<>();
        extendParams.put("id", discount.getId());
        Result<ApprovalStartDTO> approvalResult = iSysApprovalService.start(SystemBusinessType.OUTBOUND_TRAVEL.getCode(),
                SysApprovalType.DISCOUNT_OUTTRA.getCode(), req.getOrderId(),
                req.getUserId(), null, JSON.toJSONString(extendParams));
        if (!approvalResult.isSuccess()) {
        	log.error(approvalResult.getMsg());
            throw new BusinessException(SystemError.SYS_500);
        }
        discount.setApprovalId(approvalResult.getData().getApprovalId());
        boolean update = updateById(discount);
        if (!update){
            throw new BusinessException(SystemError.SYS_437);
        }
        return Result.success(discount.getId());
    }

    /**
     * 列表
     */
    @Override
    public PageResponse<SeriesOrderDiscountListDTO> list(SeriesOrderDiscountListReq req) {
        IPage<SeriesOrderDiscountListReq> pageParam = new Page<>(req.getPageNo(), req.getPageSize());
        IPage<SeriesOrderDiscountListDTO> pageResult = seriesOrderDiscountMapper.selectListBySelective(pageParam, req);
        for (SeriesOrderDiscountListDTO record : pageResult.getRecords()) {
            if (record.getCreateId() == null) {
                continue;
            }
            UserDTO crateUser = iSysUserService.queryCacheUser(record.getCreateId());
            if (crateUser != null) {
                record.setCreateName(crateUser.getFullName());
                record.setCreateDept(crateUser.getDept());
            }
        }
        PageResponse<SeriesOrderDiscountListDTO> response = new PageResponse<>(pageResult.getRecords(),
                pageResult.getCurrent() == 1,
                pageResult.getTotal() <= (pageResult.getCurrent() * pageResult.getSize()),
                pageResult.getTotal(), pageResult.getCurrent(),
                pageResult.getSize());
        return response;
    }

    /**
     * 删除
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result delete(SeriesOrderDiscountDeleteReq req) {
        QueryWrapper<SeriesOrderDiscount> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.lambda().eq(SeriesOrderDiscount::getId, req.getId());
        queryWrapper1.lambda().eq(SeriesOrderDiscount::getIsDeleted, 0);
        SeriesOrderDiscount dbDiscount = seriesOrderDiscountMapper.selectOne(queryWrapper1);
        if (dbDiscount == null || !Objects.equals(dbDiscount.getCheckStatus(), CheckStatusCode.APPROVAL_NOT_PASS.getCode())) {
            return Result.failed(SeriesOrderErrorCode.DELETE_DISCOUNT_LIMIT);
        }
        dbDiscount.setIsDeleted(IsDeletedCode.YES.getCode());
        boolean update = updateById(dbDiscount);
        if (!update){
            throw new BusinessException(SystemError.SYS_437);
        }
        return Result.success();
    }

    /**
     * 编辑
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result edit(SeriesOrderDiscountEditReq req) {
        QueryWrapper<SeriesOrderDiscount> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.lambda().eq(SeriesOrderDiscount::getId, req.getId());
        queryWrapper1.lambda().eq(SeriesOrderDiscount::getIsDeleted, 0);
        SeriesOrderDiscount dbDiscount = seriesOrderDiscountMapper.selectOne(queryWrapper1);
        if (dbDiscount == null || !Objects.equals(dbDiscount.getCheckStatus(), CheckStatusCode.APPROVAL_NOT_PASS.getCode())) {
            return Result.failed(SeriesOrderErrorCode.EDIT_DISCOUNT_LIMIT);
        }
        SeriesOrderDiscount saveObject = EntityUtil.copy(req, SeriesOrderDiscount.class);
        saveObject.setCheckStatus(CheckStatusCode.APPROVAL.getCode());
        LocalDateTime now = LocalDateTime.now();
        saveObject.setGmtModified(now);
        saveObject.setModifiedId(req.getUserId());
        saveObject.setIsDeleted(IsDeletedCode.NO.getCode());
        saveObject.setId(IdWorker.getId());
        QueryWrapper<SeriesOrderTouristInfo> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.lambda().eq(SeriesOrderTouristInfo::getOrderId, req.getOrderId());
        queryWrapper2.lambda().eq(SeriesOrderTouristInfo::getId, req.getTouristId());
        queryWrapper2.lambda().eq(SeriesOrderTouristInfo::getIsDeleted, IsDeletedCode.NO.getCode());
        SeriesOrderTouristInfo seriesOrderTouristInfo = seriesOrderTouristInfoMapper.selectOne(queryWrapper2);
        saveObject.setBeforeAmount(seriesOrderTouristInfo.getTotalReceivables());

        Map<String, Object> extendParams = new HashMap<>();
        extendParams.put("id", saveObject.getId());
        Result<ApprovalStartDTO> approvalResult = iSysApprovalService.start(SystemBusinessType.OUTBOUND_TRAVEL.getCode(),
                SysApprovalType.DISCOUNT_OUTTRA.getCode(), req.getOrderId(),
                req.getUserId(), null, JSON.toJSONString(extendParams));
        if (!approvalResult.isSuccess()) {
            throw new BusinessException(SystemError.SYS_500);
        }
        saveObject.setApprovalId(approvalResult.getData().getApprovalId());
        boolean update = updateById(saveObject);
        if (!update){
            throw new BusinessException(SystemError.SYS_437);
        }
        return Result.success(saveObject.getId());
    }

    /**
     * 审核
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result approval(SeriesOrderDiscountApprovalReq req) {
        if (req.getApprovalId() == null) {
            return Result.failed(SystemError.SYS_402);
        }
        if (!ApprovalStatus.isCheckStatus(req.getApprovalStatus())) {
            return Result.failed(SeriesOrderErrorCode.STATUS_ERROR);
        }
        QueryWrapper<SeriesOrderDiscount> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.lambda().eq(SeriesOrderDiscount::getApprovalId, req.getApprovalId());
        queryWrapper1.lambda().eq(SeriesOrderDiscount::getIsDeleted, 0);
        SeriesOrderDiscount discount = seriesOrderDiscountMapper.selectOne(queryWrapper1);
        if (discount == null){
            throw new BusinessException(SystemError.TOUR_ORDER_30018);
        }
        discount.setModifiedId(req.getUserId());
        if (Objects.equals(req.getApprovalStatus(),0)){
            //撤回
            discount.setIsDeleted(1);
            boolean update = updateById(discount);
            if (!update){
                throw new BusinessException(SystemError.SYS_437);
            }
            return Result.success(discount.getId());
        }
        discount.setCheckStatus(req.getApprovalStatus());
        boolean update = updateById(discount);
        if (!update){
            throw new BusinessException(SystemError.SYS_437);
        }
        if (Objects.equals(req.getApprovalStatus(),3)){
            //审批通过
            //订单统计
            QueryWrapper<SeriesOrderAmountStatistics> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(SeriesOrderAmountStatistics::getOrderId, discount.getOrderId());
            SeriesOrderAmountStatistics statistics = seriesOrderAmountStatisticsMapper.selectOne(queryWrapper);
            statistics.setTotalReceivables(statistics.getTotalReceivables().subtract(discount.getDiscountAmount()));
            statistics.setRemainingReceivables(statistics.getRemainingReceivables().subtract(discount.getDiscountAmount()));
            int updateOrderStatics = seriesOrderAmountStatisticsMapper.updateById(statistics);
            //游客统计
            QueryWrapper<SeriesOrderTouristInfo> queryWrapper2 = new QueryWrapper<>();
            queryWrapper2.lambda().eq(SeriesOrderTouristInfo::getOrderId, discount.getOrderId());
            queryWrapper2.lambda().eq(SeriesOrderTouristInfo::getId, discount.getTouristId());
            queryWrapper2.lambda().eq(SeriesOrderTouristInfo::getIsDeleted, IsDeletedCode.NO.getCode());
            SeriesOrderTouristInfo seriesOrderTouristInfo = seriesOrderTouristInfoMapper.selectOne(queryWrapper2);
            seriesOrderTouristInfo.setTotalReceivables(seriesOrderTouristInfo.getTotalReceivables().subtract(discount.getDiscountAmount()));
            seriesOrderTouristInfo.setRemainingReceivables(seriesOrderTouristInfo.getRemainingReceivables().subtract(discount.getDiscountAmount()));
            int updateTourist = seriesOrderTouristInfoMapper.updateById(seriesOrderTouristInfo);
            //其他费用
            SeriesOrderTouristOtherFee otherFee = new SeriesOrderTouristOtherFee();
            otherFee.setFeeType(SeriesOrderTouristOtherFeeFeeTypeCode.OTHER.getCode());
            otherFee.setOrderId(discount.getOrderId());
            otherFee.setTouristId(discount.getTouristId());
            otherFee.setFeeName(ConstantsCode.DISCOUNT.getMsg());
            otherFee.setRelationId(discount.getId());
            otherFee.setAmount(discount.getDiscountAmount());
            LocalDateTime now = LocalDateTime.now();
            otherFee.setGmtModified(now);
            otherFee.setModifiedId(req.getUserId());
            otherFee.setIsDeleted(IsDeletedCode.NO.getCode());
            int insertOtherFee = seriesOrderTouristOtherFeeMapper.insert(otherFee);
            if (updateOrderStatics <= 0 || updateTourist <= 0 || insertOtherFee <= 0){
                throw new BusinessException(SystemError.SYS_437);
            }
        }
        Result<ApprovalCheckDTO> result = iSysApprovalService.check(req.getApprovalId(), req.getUserId(),
                req.getApprovalStatus(), req.getComments());
        if (!result.isSuccess()) {
            return Result.failed(SystemError.SYS_500);
        }
        return Result.success();
    }
}
